﻿/**
 *
 * store.c
 *
 *  Created on: 2019-12-03
 *      Author: chenshisheng
 */

#include "store.h"

#define START_ADDR DATA_EEPROM_BASE

static struct
{
    uint32_t addr;
    unsigned int storageSize;  // 数据所占用存储空间，以字为单位计
}_infos[Store_Content_Max];

static const struct
{
    unsigned int  dataSize;    // 数据的实际大小，以字节为单位计
} _contentList[Store_Content_Max] =
{
    {sizeof(int)},   // Eeprom_Content_Test
    {sizeof(int)},   // Eeprom_Content_State
};

void Store_Init(void)
{
    Store_Content_t c;
    uint32_t addr;

    addr = START_ADDR;
    for(c = 0; c < Store_Content_Max; c++)
    {
        _infos[c].addr = addr;
        _infos[c].storageSize = (_contentList[c].dataSize + 1 + 3) / 4;
        addr += _infos[c].storageSize * 4;
    }

    HAL_FLASHEx_DATAEEPROM_EnableFixedTimeProgram();
    HAL_FLASHEx_DATAEEPROM_Lock();
}

static uint8_t _CheckSum(const void *data, unsigned int size)
{
    uint8_t checkSum, i;
    const uint8_t *vdata;

    vdata = data;
    checkSum = 0x55;
    for(i = 0; i < size; i++)
    {
        checkSum ^= vdata[i];
    }

    return checkSum;
}

int Store_Store(Store_Content_t content, const void *dataIn, unsigned int size)
{
    uint32_t addr;
    unsigned int i;
    uint8_t *vbuf;

    if(size != _contentList[content].dataSize)
    {
        return -1;
    }

    if(HAL_FLASHEx_DATAEEPROM_Unlock() != HAL_OK)
    {
        return -2;
    }

    uint32_t buf[_infos[content].storageSize];

    memcpy(buf, dataIn, size);
    vbuf = (uint8_t *)buf;
    vbuf[size] = _CheckSum(dataIn, size);

    addr = _infos[content].addr;
    for(i = 0; i < _infos[content].storageSize; i++)
    {
        if(HAL_FLASHEx_DATAEEPROM_Program(TYPEPROGRAMDATA_WORD, addr, buf[i]) != HAL_OK)
        {
            return -3;
        }

        addr += 4;
    }

    HAL_FLASHEx_DATAEEPROM_Lock();
    return 0;
}

int Store_Load(Store_Content_t content, void *dataOut, unsigned int size)
{
    uint32_t *addr;
    uint8_t i, checksum;
    uint8_t *vbuf;

    if(size != _contentList[content].dataSize)
    {
        return -1;
    }

    uint32_t buf[_infos[content].storageSize];

    addr = (uint32_t *)_infos[content].addr;
    for(i = 0; i < _infos[content].storageSize; i++)
    {
        buf[i] = *addr;
        addr += 1;
    }

    vbuf = (uint8_t *)buf;
    checksum = vbuf[size];
    if(checksum != _CheckSum(buf, size))
    {
        return -2;
    }

    memcpy(dataOut, buf, size);
    return 0;
}

void Store_Test(void)
{
    int t;

    if(Store_Load(Store_Content_Test, &t, sizeof(t)) != 0)
    {
        t = 0;
    }

    t ++;
    Store_Store(Store_Content_Test, &t, sizeof(t));
    debug("Store: %d\n", t);
}

